#include "Subcase.h"

#include <iostream>

#include "Utility/Logging/SGLogger.h"

#include "DataStructure/Common/Out.h"

using SG::DataStructure::Common::Id;
using SG::DataStructure::FEM::Subcase;

const std::string Subcase::SC_MAINKEY   = "MAIN_KEY";    // 记录等号右侧
const std::string Subcase::SC_VECTORKEY = "VECTOR_KEY";  // 记录（）内没有value的项，是一个string array
const std::string Subcase::SC_MAPKEY    = "MAP_KEY";     // 记录（）内有value的项，是一个Parameter

static const std::string ANALYSIS = "SOL";

bool SG::DataStructure::FEM::Subcase::ParseParameter (ControlInfo& controInfo) const
{
    if (!m_parameter.Has (controInfo.m_Key))
    {
        return false;
    }
    auto caseParameter = m_parameter[controInfo.m_Key];
    controInfo.m_Vaule = m_parameter[controInfo.m_Key][SC_MAINKEY].GetString ();
    if (caseParameter.Has (SC_VECTORKEY))
    {
        controInfo.m_vecKeys = m_parameter[controInfo.m_Key][SC_VECTORKEY].GetStringArray ();
    }

    if (caseParameter.Has (SC_MAPKEY))
    {
        auto mapPara = m_parameter[controInfo.m_Key][SC_MAPKEY];
        for (auto iter = mapPara.begin (); iter != mapPara.end (); iter++)
        {
            auto parameter = *iter;
            controInfo.m_mapKeys.insert (std::pair<std::string, std::string> (iter.name (), parameter[iter.name ()].GetString ()));
        }
    }
    return true;
}

void SG::DataStructure::FEM::Subcase::AddParameter (const ControlInfo& controInfo)
{
    SG::Utility::SGParameter controParameter;
    controParameter.AddString (SC_MAINKEY, controInfo.m_Vaule);

    if (controInfo.m_vecKeys.empty ())
    {
        controParameter.AddStringArray (SC_VECTORKEY, controInfo.m_vecKeys);
    }
    if (controInfo.m_mapKeys.empty ())
    {
        SG::Utility::SGParameter mapParameter;
        for (const auto& iter : controInfo.m_mapKeys)
        {
            mapParameter.AddString (iter.first, iter.second);
        }
        controParameter.AddValue (SC_MAPKEY, mapParameter);
    }
    m_parameter.AddValue (controInfo.m_Key, controParameter);
}

/// @brief 获取工况号
SG::DataStructure::Common::Id SG::DataStructure::FEM::Subcase::GetSubcaseId () const
{
    Id          caseId = 0;
    ControlInfo controlInfo ("SUBCASE");
    if (ParseParameter (_OUT controlInfo))
    {
        caseId = std::stoi (controlInfo.m_Vaule);
    }
    return caseId;
}

SG::DataStructure::FEM::SOLType Subcase::GetSOLType () const
{
    // todo(wxc) 后续使用magic_enum改造
    ControlInfo controlInfo (ANALYSIS);
    if (!ParseParameter (controlInfo))
    {
        SGError << "analysis type not found！";
        return SOLType::SOL_UNKNOWN;
    }

    return SOLType (std::stoi (controlInfo.m_Vaule));
}

Id SG::DataStructure::FEM::Subcase::GetSPCId () const
{
    Id          sid{ 0 };
    ControlInfo controlInfo ("SPC");
    if (ParseParameter (controlInfo))
    {
        sid = std::stoi (controlInfo.m_Vaule);
    }

    return sid;
}

Id SG::DataStructure::FEM::Subcase::GetMPCId () const
{
    Id          mpc{ 0 };
    ControlInfo controlInfo ("MPC");
    if (ParseParameter (controlInfo))
    {
        mpc = std::stoi (controlInfo.m_Vaule);
    }

    return mpc;
}

Id SG::DataStructure::FEM::Subcase::GetLoadId () const
{
    Id          load{ 0 };
    ControlInfo controlInfo ("LOAD");
    if (ParseParameter (controlInfo))
    {
        load = std::stoi (controlInfo.m_Vaule);
    }

    return load;
}

Id SG::DataStructure::FEM::Subcase::GetDLoadId () const
{
    Id          Dload{ 0 };
    ControlInfo controlInfo ("DLOAD");
    if (ParseParameter (controlInfo))
    {
        Dload = std::stoi (controlInfo.m_Vaule);
    }

    return Dload;
}

Id SG::DataStructure::FEM::Subcase::GetStaticSubId () const
{
    Id          StaticSub{ 0 };
    ControlInfo controlInfo ("STATSUB");
    if (ParseParameter (controlInfo))
    {
        StaticSub = std::stoi (controlInfo.m_Vaule);
    }

    return StaticSub;
}

Id SG::DataStructure::FEM::Subcase::GetMethodId () const
{
    Id          Method{ 0 };
    ControlInfo controlInfo ("METHOD");
    if (ParseParameter (controlInfo))
    {
        Method = std::stoi (controlInfo.m_Vaule);
    }

    return Method;
}

Id SG::DataStructure::FEM::Subcase::GetCMethodId () const
{
    Id          Method{ 0 };
    ControlInfo controlInfo ("CMETHOD");
    if (ParseParameter (controlInfo))
    {
        Method = std::stoi (controlInfo.m_Vaule);
    }

    return Method;
}

Id SG::DataStructure::FEM::Subcase::GetTSTEPId () const
{
    Id          TSTEP{ 0 };
    ControlInfo controlInfo ("TSTEP");
    if (ParseParameter (controlInfo))
    {
        TSTEP = std::stoi (controlInfo.m_Vaule);
    }

    return TSTEP;
}

bool SG::DataStructure::FEM::Subcase::HasLoadset () const
{
    ControlInfo controlInfo ("LOADSET");
    return ParseParameter (controlInfo);
}

Id SG::DataStructure::FEM::Subcase::GetLoadsetId () const
{
    Id          Loadset{ 0 };
    ControlInfo controlInfo ("LOADSET");
    if (ParseParameter (controlInfo))
    {
        Loadset = std::stoi (controlInfo.m_Vaule);
    }

    return Loadset;
}

Id SG::DataStructure::FEM::Subcase::GetFrequencyId () const
{
    Id          Frequency{ 0 };
    ControlInfo controlInfo ("FREQUENCY");
    if (ParseParameter (controlInfo))
    {
        Frequency = std::stoi (controlInfo.m_Vaule);
    }

    return Frequency;
}
Id SG::DataStructure::FEM::Subcase::GetRCROSSId () const
{
    Id          RCROSS{ 0 };
    ControlInfo controlInfo ("RCROSS");
    if (ParseParameter (controlInfo))
    {
        RCROSS= std::stoi (controlInfo.m_Vaule);
    }

    return RCROSS;
}
Id SG::DataStructure::FEM::Subcase::GetRANDPSId () const
{
    Id          RANDPS{ 0 };
    ControlInfo controlInfo ("RANDOM");
    if (ParseParameter (controlInfo))
    {
        RANDPS= std::stoi (controlInfo.m_Vaule);
    }

    return RANDPS;
}
Id SG::DataStructure::FEM::Subcase::GetSdampingId () const
{
    Id          Sdamping{ 0 };
    ControlInfo controlInfo ("SDAMPING");
    if (ParseParameter (controlInfo))
    {
        Sdamping = std::stoi (controlInfo.m_Vaule);
    }

    return Sdamping;
}

Id SG::DataStructure::FEM::Subcase::GetICId (SG::DataStructure::FEM::InitConditonType& type) const
{
    Id          IC{ 0 };
    ControlInfo controlInfo ("IC");
    if (ParseParameter (controlInfo))
    {
        IC = std::stoi (controlInfo.m_Vaule);
    }

    type = InitConditonType::INITCONDTYPE_PHYSICAL;

    return IC;
}

Id SG::DataStructure::FEM::Subcase::GetModeSelectId () const
{
    Id          ModeSelect{ 0 };
    ControlInfo controlInfo ("MODESELECT");
    if (ParseParameter (controlInfo))
    {
        ModeSelect = std::stoi (controlInfo.m_Vaule);
    }

    return ModeSelect;
}

Id SG::DataStructure::FEM::Subcase::GetModesId () const
{
    Id          Modes{ 0 };
    ControlInfo controlInfo ("MODES");
    if (ParseParameter (controlInfo))
    {
        Modes = std::stoi (controlInfo.m_Vaule);
    }

    return Modes;
}
Id SG::DataStructure::FEM::Subcase::GetNLPARMId () const
{
    Id          NLPARM{ 0 };
    ControlInfo controlInfo ("NLPARM");
    if (ParseParameter (controlInfo))
    {
        NLPARM = std::stoi (controlInfo.m_Vaule);
    }

    return NLPARM;
}

bool SG::DataStructure::FEM::Subcase::GetFIntOutputSetting (bool& all, int& setId) const
{
    ControlInfo controlInfo ("ELFORCE");
    if (ParseParameter (controlInfo))
    {
        const std::string& set = controlInfo.m_Vaule;
        if (0 == set.compare ("ALL"))
        {
            all = true;
        }
        else
        {
            setId = std::stoi (set);
        }
        return true;
    }

    // 没有 ELFORCE字段
    return false;
}